<script setup>
import { onMounted, ref, watch } from 'vue'

const props = defineProps({
  show: {
    default: false,
    type: Boolean
  },
  duration: { // 动画执行时长(毫秒)
    default: 400,
    type: [String, Number]
  },
  direction: { // 控制关闭滑动的方向
    default: 'down', // down 向下   right 向右
    type: String
  }
})
const emits = defineEmits(['update:show'])

const d = props.direction === 'down' ? 'clientY' : props.direction === 'right' ? 'clientX' : 'clientY'

const animationDuration = ref(+props.duration)

const popupContentRef = ref(null) // 弹出容器dom
const popupHeight = ref(0) // 弹窗容器的高度
onMounted(() => {
  popupHeight.value = popupContentRef.value.clientHeight

  // 给弹窗添加滑动关闭事件
  function start(e) {
    slideTime.value.push(new Date().getTime())
    displacement.value = e.changedTouches[0][d]
  }
  function move(e) {
    // 滑动的时候时间设置为0 关闭过渡效果
    animationDuration.value = 0

    displacement.value = e.changedTouches[0][d]
  }
  function end(e) {
    // 重新设置过度时间
    animationDuration.value = 400

    displacement.value = e.changedTouches[0][d]

    slideTime.value.push(new Date().getTime())

    // 关闭规则 参考抖音评论区逻辑
    /*
      1.在快速滑动下（500ms内） 只需要很少的距离就可以关闭
      2.在慢速滑动下（超过500ms） 
            1）向下滑动 滑动距离应超过弹窗高度的一半
            2）向左滑动 滑动距离应超过弹窗(弹窗一般宽度与文档可视区一致)的宽度1/3
    */
    if(slideTime.value[0] && slideTime.value[1]){
      if(slideTime.value[1] - slideTime.value[0] < 50 || expandHeight.value <= 50){ // 滑动操作间隔时间小于50ms 或者 滑动距离小于50px  不执行关闭
        // 恢复弹出状态
        translateY.value = 'translateY(0%)'
        displacement.value = 0
        expandHeight.value = 0
        return;
      }
      console.log(slideTime.value[1] - slideTime.value[0]);
      if(slideTime.value[1] - slideTime.value[0] < 500){
        close()
      } else {
        if(props.direction === 'down') {
          if(expandHeight.value < (popupHeight.value / 2)){
            // 恢复弹出状态
            translateY.value = 'translateY(0%)'
            displacement.value = 0
            expandHeight.value = 0
          } else {
            close()
          }
        } else {
          if(expandHeight.value < (document.body.clientWidth / 3)){
            // 恢复弹出状态
            translateY.value = 'translateY(0%)'
            displacement.value = 0
            expandHeight.value = 0
          } else {
            close()
          } 
        }
      }
    } else { // 恢复弹出状态
      translateY.value = 'translateY(0%)'
      displacement.value = 0
      expandHeight.value = 0
    }
  }
  popupContentRef.value.addEventListener('touchstart', start)
  popupContentRef.value.addEventListener('touchmove', move)
  popupContentRef.value.addEventListener('touchend', end)
})

const showMark = ref(false)
const markOpacity = ref(0)
const translateY = ref('translateY(100%)') // 弹出容器的偏移量
const displacement = ref(0) // 记录当前滑动的y点坐标
const slideTime = ref([]) // 记录开始滑动和结束滑动的时间
watch(() => props.show, newVal => {
  if(newVal){
    translateY.value = 'translateY(0%)'
    markOpacity.value = 1
    showMark.value = true
  } else {
    console.log(11);
    translateY.value = 'translateY(100%)'
    markOpacity.value = 0
    setTimeout(() => {
      showMark.value = false
      slideTime.value = []
    }, animationDuration.value)
  }
})
const expandHeight = ref(0) // 展开高度 0 为全部展开
watch(displacement, (newVal, oldVal) => {
  if(oldVal <= 0){ return }
  const distance = newVal - oldVal
  expandHeight.value += distance
  if(expandHeight.value < 0) {
    expandHeight.value = 0
  } else if (expandHeight.value > popupHeight.value){
    expandHeight.value = popupHeight.value
  }
  translateY.value = `translateY(${expandHeight.value}px)`
})

const close = () => {
  emits('update:show', false)
}
</script>

<template>
  <div 
    class="my-popup-mark" 
    :style="{
      opacity: markOpacity,
      transitionDuration: animationDuration / 1000 + 's'
    }"
    v-show="showMark"
    @click="close"></div>
  <div 
    class="my-popup" 
    ref="popupContentRef"
    :style="{
      transform: translateY,
      transitionDuration: animationDuration / 1000 + 's'
    }">
    <slot></slot>
  </div>
</template>

<style lang="scss" scoped>
.my-popup-mark{
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1999;
  transition: all;
  background-color: rgba(0, 0, 0, .5);
}
.my-popup{
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  background-color: #fff;
  z-index: 2000;
  transition: all;
  max-height: 100%;
  overflow-y: auto;
}
</style>
